////////////////////////////////////////////
// 这里实现标签页的切换
////////////////////////////////////////////

function initSwitchTab() {
    // 1. 先获取到相关的元素(标签页的按钮, 会话列表, 好友列表)
    let tabSession = document.querySelector('.tab .tab-session');
    let tabFriend = document.querySelector('.tab .tab-friend');
    // querySelectorAll 可以同时选中多个元素. 得到的结果是个数组
    // [0] 就是会话列表
    // [1] 就是好友列表
    let lists = document.querySelectorAll('.list');
    // 2. 针对标签页按钮, 注册点击事件.
    //    如果是点击 会话标签按钮, 就把会话标签按钮的背景图片进行设置.
    //    同时把会话列表显示出来, 把好友列表隐藏
    //    如果是点击 好友标签按钮, 就把好友标签按钮的背景图片进行设置.
    //    同时把好友列表显示出来, 把会话列表进行隐藏
    tabSession.onclick = function() {
        // a) 设置图标
        tabSession.style.backgroundImage = 'url(img/对话.png)';
        tabFriend.style.backgroundImage = 'url(img/用户2.png)';
        // b) 让会话列表显示出来, 让好友列表进行隐藏
        lists[0].classList = 'list';
        lists[1].classList = 'list hide';
    }

    tabFriend.onclick = function() {
        // a) 设置图标
        tabSession.style.backgroundImage = 'url(img/对话2.png)';
        tabFriend.style.backgroundImage = 'url(img/用户.png)'
        // b) 让好友列表显示, 让会话列表隐藏
        lists[0].classList = 'list hide';
        lists[1].classList = 'list';
    }
}

initSwitchTab();

/////////////////////////////////////////////////////
// 操作 websocket
/////////////////////////////////////////////////////
// let websocket = new WebSocket("ws://127.0.0.1:8080/webSocketMessage");
let websocket = new WebSocket("ws://" + location.host + "/webSocketMessage");

websocket.onopen = function() {
    console.log("建立连接!");
}
websocket.onerror = function(){
    console.log("连接异常断开!");
}

websocket.onclose = function() {
    console.log("连接关闭!");
}
websocket.onmessage = function(e){
    console.log("收到消息: " + e.data);
    //收到的是json字符串,需要将其转化为JSON对象:
    let  resp = JSON.parse(e.data);
    if(resp.type == 'message'){
    // 处理消息:
        handlerMessage(resp);
    }else{
        console.log("消息格式有误: "+resp.message);
    }
}

function handlerMessage(resp){
//     客户端收到消息后,需要将消息展示出来:
//     右侧的消息列表,会话区的最近一条消息 这两个地方
// 1.根据响应中的sessionId,获取对应的li标签:
//     若li标签存在,则更新最新的一条消息,不存在则创建li标签,并将其置顶
    let sessionLi = findSessionLi(resp.sessionId);
    if(sessionLi==null){
        //创建新的Li标签
        sessionLi = document.createElement("li");
        sessionLi.setAttribute("sessionId",resp.sessionId);
        sessionLi.innerHTML = '<h3>'+resp.fromName+'</h3>'+
            '<p></p>';
    // 为新的会话添加一个点击事件:
        sessionLi.onclick = function(){
            clickSession(sessionLi);
        }
    }
    //2.将新的消息显示到预览区:
    let p = sessionLi.querySelector('p');
    p.innerHTML = resp.content;
    if (p.innerHTML.length > 10) {
        p.innerHTML = p.innerHTML.substring(0, 10) + '...';
    }
    //3.将收到新消息的会话在会话列表置顶
    let sessionListUL = document.querySelector('#session-list');
    sessionListUL.insertBefore(sessionLi, sessionListUL.children[0]);
//  4.若当前会话处于点击状态,将其在右侧的消息区进行显示历史消息,且将滚动条至于最新的消息状态:
    if (sessionLi.className == 'selected') {
        // 把消息列表添加一个新消息.
        let messageShowDiv = document.querySelector('.right .message-show');
        addMessage(messageShowDiv, resp);
        scrollBottom(messageShowDiv);
    }

}


// 根据sessionId获取指定会话
function findSessionLi(sessionId){
    let sessionLis = document.querySelectorAll('#session-list li');
    for(let s of sessionLis){
        let sessionId1 = s.getAttribute("sessionId");
        if(sessionId1 == sessionId){
            return s;
        }
    }
    return null;
}


function initSendButton() {
    // 1. 获取到发送按钮 和 消息输入框
    let sendButton = document.querySelector('.right .ctrl button');
    let messageInput = document.querySelector('.right .message-input');
    // 2. 给发送按钮注册一个点击事件
    sendButton.onclick = function() {
        // a) 先针对输入框的内容做个简单判定. 比如输入框内容为空, 则啥都不干
        if (!messageInput.value) {
            // value 的值是 null 或者 '' 都会触发这个条件
            return;
        }
        // b) 获取当前选中的 li 标签的 sessionId
        let selectedLi = document.querySelector('#session-list .selected');
        if (selectedLi == null) {
            // 当前没有 li 标签被选中.
            return;
        }
        let sessionId = selectedLi.getAttribute('sessionId');
        // c) 构造 json 数据
        let req = {
            type: 'message',
            sessionId: sessionId,
            content: messageInput.value
        };
        req = JSON.stringify(req);
        console.log("[websocket] send: " + req);
        // d) 通过 websocket 发送消息
        websocket.send(req);
        // e) 发送完成之后, 清空之前的输入框
        messageInput.value = '';
    }
}

initSendButton();


/////////////////////////////////////////////////////
// 从服务器获取到用户登录数据
/////////////////////////////////////////////////////
function getUserInfo(){
    $.ajax({
        url:'userinfo',
        type:'get',
        success:function(body){
            if(body && body.userId>0){
                // 如果结果有效, 则把用户名显示到界面上.
                // 同时也可以记录 userId 到 html 标签的属性中. (以备后用)
                let userDiv = document.querySelector('.main .left .user');
                userDiv.innerHTML = body.username;
                userDiv.setAttribute("user-id", body.userId);
            } else {
                // 如果结果无效, 当前未登录! 则跳转到登录页面.
                alert("当前用户未登录!");
                location.assign('login.html');
            }
        }
    });
}
//调用方法:
getUserInfo();
//构造好友列表

function getFriendList(){
    $.ajax({
        url:'friendList',
        type:'get',
        success:function(body){
            // 1.先把之前的好友列表清空
            let friendList = document.querySelector('#friend-list');
            friendList.innerHTML = '';
            // 2.遍历body,把服务器响应的结果拼接到好友列表上
            for(let friend of body){
                let li = document.createElement('li');
                li.innerHTML = '<h3>' +friend.friendName +'</h3>';
                li.setAttribute('friend-id',friend.friendId);
                friendList.appendChild(li);

                // 为每个好友添加一个点击事件,点击后,就在会话列表置顶
                li.onclick = function() {
                    clickFriend(friend);
                }
            }
        },
        error:function(){
            alert("获取好友列表失败！");
        }
    });
}
getFriendList();

//获取会话列表:
function getSessionList(){
    $.ajax({
        type:'get',
        url:'sessionList',
        success:function(body){
        //     1.清空之前的消息列表
            let sessionList = document.querySelector('#session-list');
            sessionList.innerHTML = '';
        //     拼接上服务器返回的消息数据
            for(let session of body){
                // 针对最后一条会话,过长的进行截断
                if(session.lastMessage.length>10){
                    session.lastMessage = session.lastMessage.substring(0,10)+'...';
                }
                let li = document.createElement('li');
                li.innerHTML = '<h3>' +session.friends[0].friendName + '</h3>'
                +'<p> ' + session.lastMessage + '</p>';
                li.setAttribute("sessionId",session.sessionId);
                sessionList.appendChild(li);

            //     为选中的会话设置一个点击事件:进行高亮
                li.onclick= function() {
                    clickSession(li);
                }
            }
        },
        error:function(){
            alert("获取消息列表失败!");
        }
    });
}
getSessionList();

// 设置高亮,点击会话之后,就将其置为高亮状态:
function clickSession(currentLi){
    // 1.获取所有消息列表
    let allLi = document.querySelectorAll('#session-list>li');
//     2.将选中的消息进行高亮
    activeSession(allLi,currentLi);
//     3.获取指定会话的历史消息
    let sessionId = currentLi.getAttribute("sessionId");
    getHistorySession(sessionId);
}

//设置高亮
function activeSession(allLi,currentLi){
//     循环遍历,将选中的消息进行高亮设置,未被选中的className属性置为''
    for(let li of allLi){
        if(li==currentLi){
            li.className = 'selected';
        }else {
            li.className = '';
        }
    }
}

//获取指定会话的历史消息
function getHistorySession(sessionId){
//     1.先将消息显示区域清空,然后再拼接服务器返回的消息
//     获取到消息区域标签:
    let titleDiv = document.querySelector('.right .title');
    // 先将其清空
    titleDiv.innerHTML = '';
    // 获取到消息内容显示区标签,将其清空:
    let messageShowDiv = document.querySelector('.right .message-show');
    messageShowDiv.innerHTML = '';
    //2.重新获取会话标题:好友名字
    // 找到左侧会话列表中带有selected标签的(高亮的),然后获取其h3标签,获取到名字
    let selectedH3 = document.querySelector('#session-list .selected>h3');
//     此时selectedH3可能是不存在的,当刚进入聊天程序中时:
    if(selectedH3){
        titleDiv.innerHTML = selectedH3.innerHTML;
    }
//     3.发送ajax,获取会话的历史消息:
    $.ajax({
        url:'message?sessionId='+sessionId,
        type:'get',
        success:function(body){
        //     返回的body是一个js对象,里面的每一条数据时一个消息,进行遍历即可:
            for(let message of body){
                // 通过该方法将每一条消息添加到消息区域:
                addMessage(messageShowDiv,message);
            }
        //让每次点击一条会话,先显示的是最新的消息,而不是要再从上往下翻:
            scrollBottom(messageShowDiv);
        },
        error:function(){
            alert("获取历史消息失败!");
        }
    });
}
// 拼接消息,并显示在消息框中
function addMessage(messageShowDiv,message){
//     构造消息标签:
    let messageDiv  = document.createElement("div");
//     判断当前消息是自己发的,还是别人发的,确定消息应该靠左,还是靠右
//     通过当前消息的fromName和username进行对比判断:
//     获取userName:
    let selfUserName = document.querySelector('.left .user').innerHTML;
    if(message.fromName == selfUserName){
    //     是自己发的消息,要靠近右面:
        messageDiv.className = 'message message-right';
    }else{
        messageDiv.className = 'message message-left';
    }
//     进行消息内容拼接:
    messageDiv.innerHTML = '<div class="box">'
        + '<h4>' + message.fromName + '</h4>'
        + '<p>' + message.content + '</p>'
        + '</div>';
    // 将品号的一条消息放到消息显示框中:
    messageShowDiv.appendChild(messageDiv);
}

// 让每次点击一条会话,先显示的是最新的消息,让消息列表的滚动条直接在最下面
function scrollBottom(elem){
    // 1. 获取到可视区域的高度
    let clientHeight = elem.offsetHeight;
    // 2. 获取到内容的总高度
    let scrollHeight = elem.scrollHeight;
    // 3. 进行滚动操作, 第一个参数是水平方向滚动的尺寸. 第二个参数是垂直方向滚动的尺寸
    elem.scrollTo(0, scrollHeight - clientHeight);
}

// 点击好友列表,触发该函数,显示在回话列表,并置顶
function clickFriend(friend){
//     1.判断当前好友是否已经存在会话,
//     再创建一个方法实现:
//     参数是好友名,找到了就返回对应的会话列表的li标签,未找到就返回null
    let sessionLi = findSessionByName(friend.friendName);
    // 获取到会话列表标签:
    let sessionList = document.querySelector('#session-list');
    if(sessionLi!=null){
//     存在就直接显示在会话区,并置顶该会话
//         置顶:
//      insertBefore方法(a,b):将找到的a标签,查到b标签的前面,children[0]就是会话列表的第一个li标签,
//         插到他的前面,就是置顶的效果了:
        sessionList.insertBefore(sessionLi,sessionList.children[0]);
    //     高亮:
    //     通过模拟点击事件,触发高亮效果
        sessionLi.click();
    //     该会话已经存在会话列表中,还可以通过调用高亮方法,进行高亮设置:clickSession(sessionLi)
    }else{
//     不存在就创建新的会话,并显示在会话区,并置顶高亮:
//         创建li标签,并向服务器返回数据
//         构建li标签:
        sessionLi = document.createElement("li");
        // 由于是最新的数据,因此没有最近一条消息:
        sessionLi.innerHTML = "<h3>"+friend.friendName+"</h3>"+"<p></p>";
        // 将其插入到会话的第一行,进行置顶:
        sessionList.insertBefore(sessionLi,sessionList.children[0]);
    //     为新添加的li标签添加点击事件,并点击:
        sessionLi.onclick = function(){
            clickSession(sessionLi);
        }
        sessionLi.click();
    // 将数据通知给服务器:在数据库中添加数据
        createSession(friend.friendId,sessionLi);
    }
    // 4. 还需要把标签页给切换到 会话列表.
    //    找到会话列表标签页按钮, 模拟一个点击操作即可.
    let tabSession = document.querySelector('.tab .tab-session');
    tabSession.click();
}

// 查找当前好友是否已经存在会话:
function findSessionByName(friendName){
//     遍历会话列表,查找是否存在该好友的会话:
    let sessionLis = document.querySelectorAll('#session-list>li');
    for(let sessionLi of sessionLis){
    //     进一步获取li内部的h3标签,找到名字
        let h3 = sessionLi.querySelector('h3');
        if(h3.innerHTML == friendName){
            // 找到就返回对应的li标签:
            return sessionLi;
        }
    }
    return null;
}

// 将新创建的会话数据 返回给服务器:
function createSession(friendId,sessionLi){
    $.ajax({
        url:'session?toUserId='+friendId,
        type:'post',
        success:function(body){
            console.log("新建会话成功:sessionId:"+body.sessionId);
            sessionLi.setAttribute("sessionId",body.sessionId);
        },
        error:function(){
            alert("新建会话失败!");
        }
    });
}